﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Soft.Service
{
    /// <summary>
    /// 被调度的任务类
    /// </summary>
    public sealed class SchedulingTask : ErrorResponse, IDebug
    {

        public SchedulingTask(JobInstance instance, string param, bool debug)
        {
            if (instance == null)
            {
                throw new ArgumentNullException("instance");
            }
            this.mInstance = instance;
            this.Name = instance.Name;
            this.mRunParam = param;
            this.TaskInfo = new TaskInformation();
            this.Debug = debug;
        }


        /// <summary>
        /// 任务输出事件（在调试模式下任务执行时，对外输出信息）
        /// </summary>
        public event InformationEventHandle Information;


        /// <summary>
        /// 执行任务
        /// </summary>
        /// <param name="now"></param>
        public void TryRun(DateTime now)
        {
            if (!this.TaskInfo.Enabled)
            {
                return;
            }
            now = now.LowPrecision();
            if (this.mLastRunTime == now)
            {
                return;
            }
            object obj = this.mThreadSign;
            lock (obj)
            {
                if (!this.Running)
                {
                    //固定时间执行
                    if (this.TaskInfo.RepeatMode == ScheduleRepeatMode.Fix)
                    {
                        if (!this.TaskInfo.StartTime.IsItsTime(now))
                        {
                            return;
                        }
                    }
                    ///自定义模式
                    else if (this.TaskInfo.RepeatMode == ScheduleRepeatMode.Custom)
                    {
                        if (this.TaskInfo.BeginTime != DateTime.MinValue)
                        {
                            if (this.mNextTime == DateTime.MinValue)
                            {
                                this.mNextTime = this.TaskInfo.BeginTime;
                                while (this.mNextTime < now)
                                {
                                    this.mNextTime = this.mNextTime.Add(this.TaskInfo.Cycle);
                                }
                            }
                            if (this.TaskInfo.BeginTime > now)
                            {
                                return;
                            }
                        }
                        if (this.TaskInfo.Delayed && this.mNextTime == DateTime.MinValue)
                        {
                            this.mNextTime = now.Add(this.TaskInfo.Cycle);
                            return;
                        }
                        if (this.mNextTime != DateTime.MinValue && (this.mNextTime.Date != now.Date || this.mNextTime.Hour != now.Hour || this.mNextTime.Minute != now.Minute || this.mNextTime.Second != now.Second))
                        {
                            if (this.mNextTime < now)
                            {
                                do
                                {
                                    this.mNextTime = now.Add(this.TaskInfo.Cycle);
                                }
                                while (this.mNextTime < now);
                            }
                            return;
                        }
                        this.mNextTime = now.Add(this.TaskInfo.Cycle);
                    }
                    this.mLastRunTime = now;
                    ThreadPool.QueueUserWorkItem(new WaitCallback(this.OnRun));
                }
            }
        }


        /// <summary>
        /// 调度任务的名称
        /// </summary>
        public string Name { get; private set; }

      
        /// <summary>
        /// 任务相关描述信息
        /// </summary>
        public TaskInformation TaskInfo { get; private set; }

  
        /// <summary>
        /// 是否正在运行
        /// </summary>
        public bool Running { get; private set; }

   
        /// <summary>
        /// 是否是调试模式
        /// </summary>
        public bool Debug { get; private set; }


        /// <summary>
        /// 执行任务
        /// </summary>
        /// <param name="state"></param>
        private void OnRun(object state)
        {
            this.Running = true;
            try
            {
                ///获取定时任务的基类
                BaseTimedTask baseTimedTask = (BaseTimedTask)this.mInstance.Instance;
                Result result = baseTimedTask.Initialize();
                if (result.Succeed)
                {
                    ///如果是调试模式 则打开任务执行的日志
                    if (this.Debug)
                    {
                        string text = string.Format("Starting timed task...[{0}]", string.IsNullOrWhiteSpace(this.Name) ? baseTimedTask.TaskName : (this.Name + "." + baseTimedTask.TaskName));
                        text = text + "\r\n\tRepeatMode: " + this.TaskInfo.RepeatMode.ToString();
                        if (this.TaskInfo.RepeatMode == ScheduleRepeatMode.Fix)
                        {
                            text = text + "\r\n\tStartTime: " + this.TaskInfo.StartTime.ToString();
                        }
                        else
                        {
                            text = text + "\r\n\tBeginTime: " + ((this.TaskInfo.BeginTime == DateTime.MinValue) ? "Not set" : this.TaskInfo.BeginTime.ToDateTimeString(false));
                            text = text + "\r\n\tCycle: " + this.TaskInfo.Cycle.ToString();
                            text = text + "\r\n\tDelayed: " + this.TaskInfo.Delayed.ToString();
                        }
                        text = text + "\r\n\tParameter: " + this.mRunParam;
                        this.OnInformation(InformationType.Prompt, text, this);
                    }
                    //调用任务自动执行的逻辑
                    result = baseTimedTask.AutoRun(this.mRunParam);
                }
                else
                {
                    this.OnError("An error occurred when calling the initialization method of a timed task '" + baseTimedTask.TaskName + "'.Error message:" + result.Error.Text);
                }
            }
            catch (Exception e)
            {
                this.OnError(e);
            }
            finally
            {
                this.Running = false;
            }
        }

 
        private void OnInformation(InformationType type, string text, object sender)
        {
            InformationEventHandle information = this.Information;
            if (information == null)
            {
                return;
            }
            information(new Information(type, text, sender));
        }


        /// <summary>
        /// 任务实例
        /// </summary>
        private JobInstance mInstance;


        /// <summary>
        /// 任务执行的参数
        /// </summary>
        private string mRunParam;


        /// <summary>
        /// 最近的执行时间
        /// </summary>
        private DateTime mLastRunTime = DateTime.MinValue;


        /// <summary>
        /// 下次执行的时间
        /// </summary>
        private DateTime mNextTime = DateTime.MinValue;


        /// <summary>
        /// 同步锁
        /// </summary>
        private object mThreadSign = new object();
    }
}
